﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace MultiWallpaperManager
{
	/// <summary>
	/// Enumeration for desktop image background display styles.
	/// </summary>
	public enum DesktopBackgroundStyle
	{
		Tiled,
		Centered,
		Stretched
	}

	[StructLayout(LayoutKind.Sequential)]
	public class DisplayDevice
	{
		public UInt32 cb;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
		public string DeviceName;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string DeviceString;

		public UInt32 StateFlags;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string DeviceID;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string DeviceKey;
	}

	public class WindowsAPI
	{
		/// <summary>
		/// Adds the named item and its path to the Current User
		/// startup in registry.
		/// </summary>
		/// <param name="name"></param>
		/// <param name="path"></param>
		public static void AddStartupItem(string name, string path)
		{
			RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);

			key.SetValue(name, path);
		}

		/// <summary>
		/// Removes the named item from Current User startup in registry.
		/// </summary>
		/// <param name="name"></param>
		public static void RemoveStartupItem(string name)
		{
			RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);

			key.DeleteValue(name, false);
		}

		/// <summary>
		/// Set the Desktop background to the supplied image.  Image must be
		/// saved as BMP (saves to My Pictures), and uses the specified
		/// style (Tiled, Centered, Stretched).
		/// </summary>
		/// <param name="img"></param>
		/// <param name="style"></param>
		public static void SetDesktopBackground(string bmpPath, DesktopBackgroundStyle style)
		{
			// Clear the current background (releases lock on current bitmap)
			SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, "", SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);

			//Write style info to registry
			RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);

			switch (style)
			{
				case DesktopBackgroundStyle.Stretched:
					key.SetValue(@"WallpaperStyle", "2");
					key.SetValue(@"TileWallpaper", "0");
					break;

				case DesktopBackgroundStyle.Centered:
					key.SetValue(@"WallpaperStyle", "1");
					key.SetValue(@"TileWallpaper", "0");
					break;

				case DesktopBackgroundStyle.Tiled:
					key.SetValue(@"WallpaperStyle", "1");
					key.SetValue(@"TileWallpaper", "1");
					break;
			}

			SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, bmpPath, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="deviceName">obtained by Screen::DeviceName</param>
		/// <param name="adapterString"></param>
		/// <param name="monitorString"></param>
		public static void GetDeviceAndMonitorName(string deviceName, out string adapterString, out string monitorString)
		{
			adapterString = null;
			monitorString = null;

			DisplayDevice dd = new DisplayDevice();
			UInt32 iDevNum = 0;

			dd.cb = (UInt32)Marshal.SizeOf(dd);

			// get device names
			while (EnumDisplayDevices(null, iDevNum, dd, 0))
			{
				if ((dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) == DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
				{
					if (deviceName.Contains(dd.DeviceName))
					{
						adapterString = dd.DeviceString;
					}
				}

				iDevNum++;
			}

			iDevNum = 0;

			// get monitor name
			while (EnumDisplayDevices(deviceName, iDevNum, dd, 0))
			{
				if ((dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) == DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
				{
					monitorString = dd.DeviceString;
				}

				iDevNum++;
			}
		}

		public const int SPI_SETDESKWALLPAPER = 20;
		public const int SPI_SETWORKAREA = 47;
		public const int SPIF_UPDATEINIFILE = 0x01;
		public const int SPIF_SENDWININICHANGE = 0x02;

		[DllImport("user32.dll")]
		public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);

		const UInt32 DISPLAY_DEVICE_ATTACHED_TO_DESKTOP = 0x00000001;

		[DllImport("user32.dll")]
		public static extern bool EnumDisplayDevices(string lpDevice, UInt32 iDevNum,
													[In, Out] DisplayDevice lpDisplayDevice, UInt32 dwFlags);

	}
}
